<?php

namespace lite\models;

use admin\models\user\AR\UserAccountAR;
use admin\models\user\AR\UserAccountLogAR;
use common\libs\Util;
use Yii;
use lite\libs\CommonModel;
use lite\models\user\AR\UserAR;
use common\libs\RemoteHttp;


/**
 * ContactForm is the model behind the contact form.
 */
class Weixin extends CommonModel {
    private $appID;
    private $appSecret;
    private $mchId;
    private $siteAccessTokenCacheKey = 'site_access_token_lite';
    private $siteJsApiTicketCacheKey = 'site_jsapi_ticket';
    private $siteUserLoginKey = 'site_user_login_key';
    private $signKey = '&key=weixinlvacationcn1234567890abcde';
    private $recommendFriendAward = 0.5;
    private $signinCacheKey = 'signin_hongbao';

    public function __construct() {
        $this->appID = yii::$app->params['Weixin'][YII_ENV]['appID'];
        $this->appSecret = yii::$app->params['Weixin'][YII_ENV]['appSecret'];
        $this->mchId = yii::$app->params['Weixin'][YII_ENV]['mchID'];
    }

    //刷新access_token
    public function refreshToken() {

    }

    //获取用户access_token
    public function login($code) {
        if(empty($code)) {
            Yii::info("未获取Code", "access_token");
            $this->setError(-1, '未获取Code');
            return false;
        }
        $res = RemoteHttp::get("https://api.weixin.qq.com/sns/jscode2session", ['grant_type' => 'authorization_code',
                                                                                'js_code'=>$code,
                                                                                'appid' => $this->appID,
                                                                                'secret' => $this->appSecret]);
        $accessToken = json_decode($res, true);
        $isNew=false;
        if(isset($accessToken['errcode'])) {
            Yii::trace($res, 'access_token');
            $this->setError(-1, $accessToken['errmsg']);
            return false;
        } else {
            $user = UserAR::findOne(['union_id' => $accessToken['unionid']]);
            //用户不存在
            if(!$user) {
                //保存用户信息
                $isNew=true;
                $user = new UserAR();
                $user->status = 1;
                $user->name="weixin_user";
                $user->create_time = time();
                $user->update_time = time();
                $user->union_id=$accessToken['unionid'];
            }

            $user->login_time= date('Y-m-d H:i:s');
            $user->weixin_openid_lite = $accessToken['openid'];
            $user->weixin_session_key = $accessToken['session_key'];
            $user->save();


            if($isNew){
                $user_id = Yii::$app->db->getLastInsertID();
                $userAccount = new UserAccountAR();
                $userAccount->user_id = $user_id;
                $userAccount->create_time = time();
                $userAccount->score = 100;//新用户送100积分
                $userAccount->save();


                $userAccountLog = new UserAccountLogAR();
                $userAccountLog->user_id = $userAccount->user_id;
                $userAccountLog->amount = 100;
                $userAccountLog->original = 0;
                $userAccountLog->balance = 100;
                $userAccountLog->type = 'score';
                $userAccountLog->create_time = time();
                $userAccountLog->remark = '关注公众号积分奖励';
                $userAccountLog->save();
            }
        }

        $open_id=$accessToken['openid'];
        $session_key=$accessToken['session_key'];
        $third_session= md5(md5(uniqid()));
        $session_value=[
          'open_id'=>$open_id,
          'session_key'=>$session_key,
        ];
        $cache = Yii::$app->cache;
        $cache->set($third_session,serialize($session_value),3600*24);
        return $third_session;
    }

    public static function checkIsLogin($key){
        $cache = Yii::$app->cache;
        $accessToken = $cache->get($key);
        if(!$accessToken){

        }else{
            $accessToken=unserialize($accessToken);
            $user=UserAR::findOne(['weixin_openid_lite'=>$accessToken['open_id']]);
            if($user&&$user->weixin_session_key==$accessToken['session_key']){
                return $user;
            }else{

            }

        }
        return false;
    }

    //获取整站access_token 并缓存
    public function getSiteAccessToken() {
        $cache = Yii::$app->cache;
        $accessToken = $cache->get($this->siteAccessTokenCacheKey);
        if(!$accessToken) {
            $res = RemoteHttp::get("https://api.weixin.qq.com/cgi-bin/token", ['grant_type' => 'client_credential',
                                                                               'appid' => $this->appID,
                                                                               'secret' => $this->appSecret,]);
            $json = json_decode($res, true);
            if(isset($json['errcode'])) {
                Yii::error($res, $this->siteAccessTokenCacheKey);
                $this->setError(-1, $json['errmsg']);
                return false;
            } else {
                $accessToken = $json['access_token'];
                $cache->set($this->siteAccessTokenCacheKey, serialize($accessToken), $json['expires_in']);
            }
        } else {
            $accessToken = unserialize($accessToken);
        }
        return $accessToken;
    }

    //获取jsapi签名
    public function getJsApiSignature($url = null) {
        if(empty($url)) {
            $url = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
        }
        $timeStamp = time();
        $nonceStr = Util::getRandCode(16);
        $jsapiTicket = $this->getJsApiTicket();

        if($jsapiTicket === false) {
            return false;
        }
        $signatureParams = ['noncestr' => $nonceStr, 'jsapi_ticket' => $jsapiTicket, 'timestamp' => $timeStamp,
                            'url' => $url];

        $signature = $this->getSign($signatureParams, "sha1", false);
        return ['appId' => $this->appID, 'timestamp' => $timeStamp, 'nonceStr' => $nonceStr,
                'signature' => $signature,];
    }

    //获取jsapi_ticket
    public function getJsApiTicket() {
        $cache = Yii::$app->cache;
        $jsApiTicket = $cache->get($this->siteJsApiTicketCacheKey);
        if(!$jsApiTicket) {
            $access_token = $this->getSiteAccessToken();
            $res = RemoteHttp::get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token={$access_token}");
            $json = json_decode($res, true);
            if(isset($json['errcode']) && !empty($json['errcode'])) {
                Yii::error($res, $this->siteJsApiTicketCacheKey);
                $this->setError(-1, $json['errmsg']);
                return false;
            } else {
                $jsApiTicket = $json['ticket'];
                $cache->set($this->siteJsApiTicketCacheKey, serialize($jsApiTicket), $json['expires_in']);
            }
        } else {
            $jsApiTicket = unserialize($jsApiTicket);
        }
        return $jsApiTicket;
    }

    //获取微信支付签名
    public function getWxJsPaySignature($prepay_id) {
        $timeStamp = (string)time();
        $nonceStr = Util::getRandCode(16);
        $signType = "MD5";
        $package = "prepay_id=$prepay_id";

        $signatureParams = ['appId' => $this->appID, 'timeStamp' => $timeStamp, 'nonceStr' => $nonceStr,
                            'package' => $package, 'signType' => $signType];

        $paySign = $this->getSign($signatureParams, 'md5', true, $this->signKey);
        return ['appId' => $this->appID, 'timestamp' => $timeStamp, 'nonceStr' => $nonceStr, 'package' => $package,
                'signType' => $signType, 'paySign' => $paySign,];
    }

    //发起统一下单
    public function unifiedorder($product_info, $out_trade_no, $total_fee, $open_id, $prepay_id = null) {
        if(!$prepay_id) {
            $postParams = ['appid' => $this->appID, 'mch_id' => $this->mchId, 'nonce_str' => Util::getRandCode(16),
                           'sign_type' => "MD5", 'body' => mb_strcut("悠长假期-{$product_info['title']}", 0, 30, "UTF-8"),
                           'out_trade_no' => $out_trade_no,//{$product_info['title']}
                           'total_fee' => $total_fee, 'spbill_create_ip' => Util::getIp(),
                           'notify_url' => 'http://weixin.lvacation.cn/api/order/wx_notify', 'trade_type' => "JSAPI",
                           'openid' => $open_id];

            $sign = $this->getSign($postParams, "md5", true, $this->signKey);
            $postParams['sign'] = $sign;
            $xml = Util::arrayToXml($postParams);
            $res = RemoteHttp::postXmlString("https://api.mch.weixin.qq.com/pay/unifiedorder", $xml);
            Yii::error(print_r($postParams, true));
            Yii::error($res);
            $result = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);

            if(isset($result->return_code) && $result->return_code == 'SUCCESS' && $result->result_code == "SUCCESS") {
                $order_info = OrderAR::findOne(['out_order_id' => $out_trade_no]);
                $order_info->prepay_id = $result->prepay_id;
                $order_info->save();
                return $this->getWxJsPaySignature($result->prepay_id);
            } else {
                $this->setError(-1, $result->err_code_des ? $result->err_code_des : $result->return_msg);
                return false;
            }
        } else {
            return $this->getWxJsPaySignature($prepay_id);
        }

    }

    //签名
    public function getSign($signatureParams, $type = "md5", $upper_case = true, $signString = "") {
        ksort($signatureParams);
        $stringSignTemp = '';
        foreach($signatureParams as $key => $val) {
            $stringSignTemp .= $key . '=' . $val . '&';
        }
        $stringSignTemp = substr($stringSignTemp, 0, -1) . $signString;
        $stringSignTemp = $type == "md5" ? md5($stringSignTemp) : sha1($stringSignTemp);
        if($upper_case) {
            $stringSignTemp = strtoupper($stringSignTemp);
        }

        return $stringSignTemp;
    }


    //发送模板消息
    public function sendTemplateMessage($temp_code, $open_id, $params) {

        $access_token = $this->getSiteAccessToken();
        $template = yii::$app->params['WeixinTemplateMessage'][$temp_code];
        $postData = $this->getTemplateParams($params, $template);
        $postData['touser'] = $open_id;
        $res = RemoteHttp::postJson("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$access_token}", $postData);
        $json = json_decode($res, true);
        if(isset($json['errcode']) && !empty($json['errcode'])) {
            $this->setError(-1, $json['errmsg']);
            return false;
        } else {
            return true;
        }
    }


    /**
     * 红包发放
     */
    public function sendRedpack($open_id = 'ojwZ9v9UVTinUDXUmv4g-93GG2Hg', $act_name = "会员返利", $total = '1') {
        $postParams = ['nonce_str' => Util::getRandCode(16), 'mch_billno' => "LVHB" + time(), 'mch_id' => $this->mchId,
                       'wxappid' => $this->appID, 'send_name' => "悠长假期旅行网", 're_openid' => $open_id,
                       'total_amount' => "100", 'total_num' => $total, 'wishing' => "世界那么大，好好放个假",
                       'client_ip' => Util::getIp(), 'act_name' => $act_name, 'remark' => "猜越多得越多，快来抢！"];
        $sign = $this->getSign($postParams, "md5", true, $this->signKey);
        $postParams['sign'] = $sign;
        $xml = Util::arrayToXml($postParams);
        $res = RemoteHttp::postSSL("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack", $xml, 60, ['Content-Type: application/xml',
                                                                                                             'Content-Length: ' . strlen($xml)]);
        Yii::error(print_r($postParams, true));
        Yii::error($res);
        $result = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
        if(isset($result->return_code) && $result->return_code == 'SUCCESS' && $result->result_code == "SUCCESS") {
            return true;
        } else {
            $this->setError(-1, $result->err_code_des ? $result->err_code_des : $result->return_msg);
            return false;
        }
    }

    /**
     * 获取小程序二维码
     */
    public function getQrcode($scene='0',$page=''){
        $access_token = $this->getSiteAccessToken();
        $postData=['scene'=>$scene,'page'=>$page];
        $url="https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={$access_token}";
        $res = RemoteHttp::postJson($url,$postData);
        if(isset($res['errcode'])){
            $this->setError(-1,$res.errmsg);
            return false;
        }
        return $res;
    }

    /**
     * 付款
     */
    public function transfers($open_id = 'ojwZ9v9UVTinUDXUmv4g-93GG2Hg',  $total = '1') {
        $postParams = ['nonce_str' => Util::getRandCode(16), 'partner_trade_no' => "LVPAY" + time(), 'mchid' => $this->mchId,
                       'mch_appid' => $this->appID, 'check_name' => "NO_CHECK", 'openid' => $open_id,
                       'amount' => $total, 'desc' => "采购",
                       'spbill_create_ip' => Util::getIp()];
        $sign = $this->getSign($postParams, "md5", true, $this->signKey);
        $postParams['sign'] = $sign;
        $xml = Util::arrayToXml($postParams);
        $res = RemoteHttp::postSSL("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers", $xml, 60, ['Content-Type: application/xml',
                                                                                                             'Content-Length: ' . strlen($xml)]);
        Yii::error(print_r($postParams, true));
        Yii::error($res);
        $result = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
        if(isset($result->return_code) && $result->return_code == 'SUCCESS' && $result->result_code == "SUCCESS") {
            return true;
        } else {
            $this->setError(-1, $result->err_code_des ? $result->err_code_des : $result->return_msg);
            return false;
        }
    }

    /**
     * @deprecated 获取微信用户信息
     * @param $open_id
     * @return mixed
     */
    public function getUserInfo($open_id) {
        $access_token = $this->getSiteAccessToken();
        //使用access_token获取用户信息
        $userResult = RemoteHttp::get("https://api.weixin.qq.com/cgi-bin/user/info", ['access_token' => $access_token,
                                                                                      'openid' => $open_id,
                                                                                      'lang' => 'zh_CN',]);
        $userResult = preg_replace("#(\\\ue[0-9a-f]{3})#ie","addslashes('\\1')",$userResult);

        $userInfo = json_decode($userResult,true);
        if(!empty($userInfo['errcode'])) {
            $this->setError(-1, $userInfo['errmsg']);
            return false;
        }
        return $userInfo;
    }

    /**
     * @deprecated 申请二维码ticket
     * @param string $action_name
     * @param int $scene_id
     * @param string $scene_str
     * @return mixed $ticket
     */
    public function getQrcodeTicket($action_name = 'QR_SCENE', $scene_id = 1, $scene_str = '') {
        $access_token = $this->getSiteAccessToken();


        //使用access_token获取用户信息
        $qrcodeResult = RemoteHttp::post("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=$access_token", json_encode(['expire_seconds' => 2592000,
                                                                                                                                    'action_name' => $action_name,
                                                                                                                                    'scene_info' => ['scene' => ['scene_id' => $scene_id,
                                                                                                                                                                 'scene_str' => $scene_str]]]));
        $qrcode = json_decode($qrcodeResult, true);
        return $qrcode;

    }

    private function getTemplateParams($params, $temp_params) {
        foreach($params as $key => $obj) {
            $temp_params['data'][$key]['value'] = $obj;
        }
        return $temp_params;
    }

    private function responseText($object, $content, $flag = 0) {
        $textTpl = "<xml>
                    <ToUserName><![CDATA[%s]]></ToUserName>
                    <FromUserName><![CDATA[%s]]></FromUserName>
                    <CreateTime>%s</CreateTime>
                    <MsgType><![CDATA[text]]></MsgType>
                    <Content><![CDATA[%s]]></Content>
                    <FuncFlag>%d</FuncFlag>
                    </xml>";
        $resultStr = sprintf($textTpl, $object['FromUserName'], $object['ToUserName'], time(), $content, $flag);
        return $resultStr;
    }
}
